/*
 * Copyright (c) 2011 Ball State University
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * NOTE:
 * Derivative work based on the Google IO 2011 Schedule app released for open source
 * http://code.google.com/p/iosched/
 */

package edu.bsu.android.gtv.apps.bconnected.ui; 

import java.util.ArrayList;

import edu.bsu.android.gtv.apps.bconnected.R;
import edu.bsu.android.gtv.apps.bconnected.data.ConnectionData;
import edu.bsu.android.gtv.apps.bconnected.data.CourseData;
import edu.bsu.android.gtv.apps.bconnected.data.OrganizationData;
import edu.bsu.android.gtv.apps.bconnected.data.PersonData;
import edu.bsu.android.gtv.apps.bconnected.objects.Course;
import edu.bsu.android.gtv.apps.bconnected.objects.Organization;
import edu.bsu.android.gtv.apps.bconnected.objects.Person;
import edu.bsu.android.gtv.apps.bconnected.ui.base.BaseActivity;
import edu.bsu.android.gtv.apps.bconnected.util.Adapters;
import edu.bsu.android.gtv.apps.bconnected.util.AnalyticsUtils;
import edu.bsu.android.gtv.apps.bconnected.util.BSUPrivate;
import edu.bsu.android.gtv.apps.bconnected.util.Constants;
import edu.bsu.android.gtv.apps.bconnected.util.FractionalTouchDelegate;
import edu.bsu.android.gtv.apps.bconnected.util.LoginHelper;
import edu.bsu.android.gtv.apps.bconnected.util.UIUtils;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.RectF;
import android.os.Bundle;
import android.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TabHost;
import android.widget.TextView;

/**
 * A fragment that shows the personal information for a connection.  The fragment appears in the right hand column of the 
 * {@link ConnectionMultiPaneActivity} after the user selects a connection.  There is no secondary info activity as all of the
 * necessary information is displayed in the right hand column.
 * @author Kyle Parker, University Computing Services
 */
// DONE: If an instructor, should there be something other than "shared courses"? - if this is displayed, need to add a new sproc to get instructor info
// NOTE: This class is somewhat different in that it is loaded directly from the primary list fragment, unlike the others - term/course, month/event, 
// category/org.
public class ConnectionInfoFragment extends Fragment { 
    private static final String TAG = "ConnectionInfoFragment";
    private static final String TAG_SHARED_ORGANIZATIONS = "orgs"; 
    private static final String TAG_SHARED_COURSES = "courses"; 
    private static final String TAG_OTHER_COURSES = "other";  

    private TabHost mTabHost;
    private ViewGroup mRootView;
    private View mLoadingSpinner;
    private View mSharedCoursesSpinner;
    private View mSharedOrganizationsSpinner;
    private View mOtherCoursesSpinner;
    private Activity mActivity;
    private Person mPerson;
    private BroadcastReceiver mReceiver;
    private CompoundButton mStarred;

    private String mLoginGuid;
    private String mBSUID;
    private String mSearchBSUID;
    private boolean mLogin;
    private int mPersonType;
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mActivity = getActivity();
        handleLogout(); 
        handleLogin();
        AnalyticsUtils.getInstance(mActivity).trackPageView("/ConnectionInfo");
    }
    
    @Override 
    public void onDestroy() {
    	super.onResume();
    	mActivity.unregisterReceiver(mReceiver);
    }
    
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
    }

    /**
     * Method called by the ConnectionFragment to launch the activity and set the necessary values for the web service calls
     * @param bsuID
     * @param personType
     */
    public void startActivity(String bsuID, int personType) {    	
    	mSearchBSUID = bsuID;
    	mPersonType = personType;
    	
    	if (mActivity != null) {
    		loadConnectionInfo();
    	}
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        mRootView = (ViewGroup) inflater.inflate(R.layout.fragment_connection_info, null); 
        mTabHost = (TabHost) mRootView.findViewById(android.R.id.tabhost);
        mTabHost.setup();

        mLoadingSpinner = mRootView.findViewById(R.id.loading_spinner); 
        mLoadingSpinner.setVisibility(View.VISIBLE);
        
        mSharedOrganizationsSpinner = mRootView.findViewById(R.id.spinner_shared_organizations); 
        mSharedOrganizationsSpinner.setVisibility(View.VISIBLE);
        
        mOtherCoursesSpinner = mRootView.findViewById(R.id.spinner_other_courses); 
        mOtherCoursesSpinner.setVisibility(View.VISIBLE);

        mSharedCoursesSpinner = mRootView.findViewById(R.id.spinner_shared_courses); 
        mSharedCoursesSpinner.setVisibility(View.VISIBLE);
        
        mStarred = (CompoundButton) mRootView.findViewById(R.id.star_button);
        mStarred.setFocusable(true);
        mStarred.setClickable(true);
        
        // Larger target triggers star toggle
        final View starParent = mRootView.findViewById(R.id.name);
        FractionalTouchDelegate.setupDelegate(starParent, mStarred, new RectF(0.6f, 0f, 1f, 0.8f));

        setupSharedCoursesTab();
        setupOtherCoursesTab();
        setupSharedOrganizationsTab();
        
        reloadFromArguments(getArguments());
		
		// Hide the connection while the data is loading
		hideConnectionInfo();
		if (mLogin) {
			loadConnectionInfo();
		}
        
        return mRootView;
    }

    /**
     * Get the extras from the Intent
     * @param arguments
     */
    public void reloadFromArguments(Bundle arguments) {
        final Intent intent = BaseActivity.fragmentArgumentsToIntent(arguments);        
		Bundle extras = intent.getExtras(); 
		
		if (extras != null) {
			if (extras.getString(Constants.EXTRA_BSU_ID) != null) {
				mSearchBSUID = extras.getString(Constants.EXTRA_BSU_ID);
			}
			if (extras.getString(Constants.EXTRA_PERSON_TYPE_ID) != null) {
				mPersonType = Integer.parseInt(extras.getString(Constants.EXTRA_PERSON_TYPE_ID));
			}
		}
    }

    /**
     * Using a new thread, separate from the main activity, load the connection information from the service handler
     */
    private void loadConnectionInfo() {			
        Runnable load = new Runnable(){
            public void run() { 
            	try {
	            	// Depending on the member type (student or advisor) retrieve the appropriate person information
	            	if (mPersonType == Constants.VALUE_PERSON_TYPE_FACULTY || mPersonType == Constants.VALUE_PERSON_TYPE_DIRECTOR) {
	            		PersonData.initializePerson(mSearchBSUID, mBSUID, Constants.QUERY_PERSON_DIRECTORY_FACULTY, mActivity);
	            	} else {
	            		PersonData.initializePerson(mSearchBSUID, mBSUID, Constants.QUERY_PERSON_DIRECTORY_STUDENT, mActivity);
	            	}
	            	
	                if (PersonData.getPersonCount() > 0) {
	                	// This will return 1 person record - retrieve the information from the first position
	                	mPerson = PersonData.getPerson(0);
                    }
	    	    	
	        		mActivity.runOnUiThread(returnConnection);
            	} catch (Exception ex) {
                    AnalyticsUtils.getInstance(mActivity).trackPageView(TAG + ": " + ex.getMessage());
            	}
            }
        };
        
        Thread thread = new Thread(null, load, "loadConnection");
        thread.start();
    }
    
    /**
     * Display the connection info in a separate thread and when completed, set the visibility of the spinner to "gone"
     */
    private Runnable returnConnection = new Runnable(){
        public void run() {
        	displayConnection();
            mLoadingSpinner.setVisibility(View.GONE);
        }
    };

    /**
     * Using a new thread, separate from the main activity, load the shared courses from the service handler
     */
    private void loadSharedCourse() {			
        Runnable load = new Runnable(){
            public void run() { 
            	try {
            		CourseData.initializeSharedCourses(mBSUID, mSearchBSUID, mLoginGuid, mActivity);
        	    	
            		mActivity.runOnUiThread(returnSharedCourse);
            	} catch (Exception ex) {
                    AnalyticsUtils.getInstance(mActivity).trackPageView(TAG + ": " + ex.getMessage());
            	}
            }
        };
        
        Thread thread = new Thread(null, load, "loadSharedCourse");
        thread.start();
    }
    
    /**
     * Display the shared courses in a separate thread
     */
    private Runnable returnSharedCourse = new Runnable(){
        public void run() {
        	// If the call to the shared course service did not return the "error" attribute, then display the shared courses, otherwise 
        	// the expiration date has expired for the user or they are not authorized under the current credentials to access the information.
        	// When retrieving data from the .NET service handler, the BSU ID and login guid are matched against the SQL Server database.  If
        	// the combination of the two do not match, then the user is not permitted to retrieve the requested data.  The guards against
        	// someone hacking the querystring parameters to retrieve the information of another student.
        	if (CourseData.getSharedCourseAuth()) {
	        	displaySharedCourses(CourseData.getSharedCourses());

                TextView empty = ((TextView) mRootView.findViewById(R.id.empty_shared_courses));
                
	            if (CourseData.getSharedCoursesCount() == 0) {
	                empty.setVisibility(View.VISIBLE);
	            } else {
	                empty.setVisibility(View.GONE);
	            }
        	} else {
                mRootView.findViewById(R.id.connection_container).setVisibility(View.VISIBLE);
                TextView empty = ((TextView) mRootView.findViewById(R.id.empty_shared_courses));
                empty.setVisibility(View.VISIBLE);
                empty.setText(R.string.error_auth);
        	}
        	
            mSharedCoursesSpinner.setVisibility(View.GONE);
        }
    };

    /**
     * Using a new thread, separate from the main activity, load the shared organizations from the service handler
     */
    private void loadSharedOrganization() {			
        Runnable load = new Runnable(){
            public void run() { 
            	try {
            		OrganizationData.initializeSharedOrganization(mBSUID, mSearchBSUID, mActivity);
        	    	
            		mActivity.runOnUiThread(returnSharedOrganization);
            	} catch (Exception ex) {
                    AnalyticsUtils.getInstance(mActivity).trackPageView(TAG + ": " + ex.getMessage());
            	}
            }
        };
        
        Thread thread = new Thread(null, load, "loadSharedOrganization");
        thread.start();
    }
    
    /**
     * Display the shared organizations in a separate thread
     */
    private Runnable returnSharedOrganization = new Runnable(){
        public void run() {
            displaySharedOrganizations(OrganizationData.getSharedOrganizations());
            mSharedOrganizationsSpinner.setVisibility(View.GONE);

            TextView empty = ((TextView) mRootView.findViewById(R.id.empty_shared_organizations));
            
            if (OrganizationData.getSharedOrganizationCount() == 0) {
                empty.setVisibility(View.VISIBLE);
            } else {
                empty.setVisibility(View.GONE);
            }
        }
    };

    /**
     * Using a new thread, separate from the main activity, load the other courses taught by the instructor from the service handler
     */
    private void loadOtherCourse() {			
        Runnable load = new Runnable(){
            public void run() { 
            	try {
            		CourseData.initializeOtherCourses(mSearchBSUID, mActivity);
        	    	
            		mActivity.runOnUiThread(returnOtherCourse);
            	} catch (Exception ex) {
                    AnalyticsUtils.getInstance(mActivity).trackPageView(TAG + ": " + ex.getMessage());
            	}
            }
        };
        
        Thread thread = new Thread(null, load, "loadOtherCourse");
        thread.start();
    }
    
    /**
     * Display the other courses taught by the instructor in a separate thread
     */
    private Runnable returnOtherCourse = new Runnable(){
        public void run() {
            displayOtherCourses(CourseData.getOtherCourses());
            mOtherCoursesSpinner.setVisibility(View.GONE);

            TextView empty = ((TextView) mRootView.findViewById(R.id.empty_other_courses));
            
            if (CourseData.getOtherCoursesCount() == 0) {
                empty.setVisibility(View.VISIBLE);
            } else {
                empty.setVisibility(View.GONE);
            }
        }
    };
    
    /**
     * Display the connection information, set the starred status and show the shared courses, other courses and shared organizations
     */
    private void displayConnection() { 
    	if (mPerson != null) {
            mRootView.findViewById(R.id.connection_container).setVisibility(View.VISIBLE);
    		mRootView.setBackgroundResource(R.drawable.blank_background);

    		loadSharedOrganization();
        	loadOtherCourse();    		
    		loadSharedCourse();
            
    		String name;
    		
        	if (mPersonType == Constants.VALUE_PERSON_TYPE_FACULTY) {
                // If the person is an instructor, show the title, department and office, along with the "other courses" taught tab
        		name = (mPerson.getNamePrefix() + " " + mPerson.getFirstName() + " " + mPerson.getLastName() + " " + mPerson.getNameSuffix()).trim();

        		// Hide the "address" view - the instructor's address will be displayed as the department and office
        		mRootView.findViewById(R.id.address).setVisibility(View.GONE);
	            mRootView.findViewById(R.id.title).setVisibility(View.VISIBLE);
	            mRootView.findViewById(R.id.department).setVisibility(View.VISIBLE);
	            mRootView.findViewById(R.id.office).setVisibility(View.VISIBLE);

	            UIUtils.displayTextView(mRootView, R.id.title, mPerson.getTitleRank());
	            UIUtils.displayTextView(mRootView, R.id.department, mPerson.getDepartment());
	            UIUtils.displayTextView(mRootView, R.id.office, mPerson.getBuildingCode() + " " + mPerson.getRoom());
        	} else if (mPersonType == Constants.VALUE_PERSON_TYPE_DIRECTOR) {
                // If the person is an instructor, show the title, department and office, along with the "other courses" taught tab
        		name = (mPerson.getNamePrefix() + " " + mPerson.getFirstName() + " " + mPerson.getLastName() + " " + mPerson.getNameSuffix()).trim();
	    		

        		// Hide the "address" view - the instructor's address will be displayed as the department and office
	            mRootView.findViewById(R.id.address).setVisibility(View.GONE);
	            mRootView.findViewById(R.id.title).setVisibility(View.VISIBLE);
	            mRootView.findViewById(R.id.department).setVisibility(View.GONE);
	            mRootView.findViewById(R.id.office).setVisibility(View.GONE);

	    		if (mPerson.getDepartment().length() > 0 && !mPerson.getDepartment().contains(BSUPrivate.VALUE_NO_DEPARTMENT)) {
		            UIUtils.displayTextView(mRootView, R.id.title, mPerson.getTitleRank() + ", " + mPerson.getDepartment());
	    		} else {
		            UIUtils.displayTextView(mRootView, R.id.title, mPerson.getTitleRank());
	    		}
        	} else {
                if (mPerson.getPersonType() != null) {
        			mPersonType = Integer.parseInt(mPerson.getPersonType());
        		}
                
    	        // If the person is a student, hide the title, department and office, along with the "other courses" tab
	            mRootView.findViewById(R.id.department).setVisibility(View.GONE);
	            mRootView.findViewById(R.id.office).setVisibility(View.GONE);
	            
	            name = (mPerson.getFirstName() + " " + mPerson.getLastName() + " " + mPerson.getNameSuffix()).trim();
	            String address = "";
	            			//UIUtils.formatAddress(mPerson.getAddress1(), mPerson.getAddress2(), mPerson.getCity(), 
		    				//mPerson.getState(), mPerson.getZip());
	        	
	    		UIUtils.displayTextView(mRootView, R.id.address, address);
	    		
	    		switch (mPersonType) {
		    		case Constants.VALUE_PERSON_TYPE_ROOMMATE:
		    			//mPersonTitle = "Roommate";
			            UIUtils.displayTextView(mRootView, R.id.title, mPerson.getTitleRank());
			            break;
		    		case Constants.VALUE_PERSON_TYPE_RA:
		    			//mPersonTitle = "Resident Assistant (RA)";
			            UIUtils.displayTextView(mRootView, R.id.title, mPerson.getTitleRank());
			            break;
		    		case Constants.VALUE_PERSON_TYPE_FLOORMATE:
		    			//mPersonTitle = "Floormate";
			            UIUtils.displayTextView(mRootView, R.id.title, mPerson.getTitleRank());
			            break;
			         default:
			            mRootView.findViewById(R.id.title).setVisibility(View.GONE);
			            break;
	    		}
        	}
	        
            // Unregister around setting checked state to avoid triggering listener since change isn't user generated.
            mStarred.setOnCheckedChangeListener(null);
            mStarred.setChecked(mPerson.getStarred());
            mStarred.setOnCheckedChangeListener(new OnCheckedChangeListener() {
			    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
			    	ConnectionData.insertConnection(mBSUID, mLoginGuid, mSearchBSUID, mPersonType, isChecked, mActivity);
			    	//PersonData.starPerson(mActivity, mPerson.getFirstName(), mPerson.getLastName(), mPerson.getNameSuffix(), isChecked, 
			    	//		mBSUID, mSearchBSUID, mPersonType);
			    }           	
            });
            
    		UIUtils.displayTextView(mRootView, R.id.name, name);
    		UIUtils.displayTextView(mRootView, R.id.email, mPerson.getEmailAddress());
    		UIUtils.displayTextView(mRootView, R.id.phone, mPerson.getPhone());
        } else {
        	hideConnectionInfo();
    		((TextView) showConnectionInfo().findViewById(R.id.empty_connection_info)).setText(R.string.empty_connection_info);
    	}
    }

    /**
     * Hide the connection view during the load process or if the connection object is empty
     */
	private void hideConnectionInfo() {  
	    mRootView.findViewById(R.id.connection_container).setVisibility(View.GONE);	
	}

    /**
     * Show the connection view during the load process or if the connection object is empty
     */
	private View showConnectionInfo() {
		LinearLayout view = (LinearLayout) mRootView.findViewById(R.id.empty_connection_container);
		view.setVisibility(View.VISIBLE);
        view.setBackgroundResource(R.drawable.empty_my_connections);
        
        return view;
	}
    
    /**
     * Display the shared courses for the student and the connection
     * @param ArrayList<Course> sharedCourses
     */
    private void displaySharedCourses(ArrayList<Course> sharedCourses) {
    	Adapters.CourseAdapter adapter = new Adapters.CourseAdapter(mActivity, sharedCourses, Constants.TARGET_SHARED_COURSE);

        final ListView lv = ((ListView) mRootView.findViewById(R.id.shared_courses));
        lv.setAdapter(adapter);
    }
    
    /**
     * Display the shared organizations for the student and the connection
     */
    private void displaySharedOrganizations(ArrayList<Organization> sharedOrganizations) {
    	Adapters.OrganizationAdapter adapter = new Adapters.OrganizationAdapter(mActivity, sharedOrganizations, 
    			Constants.TARGET_SHARED_ORGANIZATION);

        final ListView lv = ((ListView) mRootView.findViewById(R.id.shared_organizations));
        lv.setAdapter(adapter);  
    }
    
    /**
     * Display the shared organizations for the student and the connection
     * @param ArrayList<Course> otherCourses
     */
    private void displayOtherCourses(ArrayList<Course> otherCourses) { 		
    	Adapters.CourseAdapter adapter = new Adapters.CourseAdapter(mActivity, otherCourses, Constants.TARGET_OTHER_COURSE);

        final ListView lv = ((ListView) mRootView.findViewById(R.id.other_courses));
        lv.setAdapter(adapter);
    }
    
    /**
     * Build and add "shared courses" tab.
     */
    private void setupSharedCoursesTab() {
        mTabHost.addTab(mTabHost.newTabSpec(TAG_SHARED_COURSES)
                .setIndicator(buildIndicator(R.string.tab_classmate_shared_courses))
                .setContent(R.id.tab_shared_course));
    }
    
    /**
     * Build and add "shared organizations" tab.
     */
    private void setupSharedOrganizationsTab() {
        mTabHost.addTab(mTabHost.newTabSpec(TAG_SHARED_ORGANIZATIONS) 
                .setIndicator(buildIndicator(R.string.tab_member_shared_organizations))
                .setContent(R.id.tab_shared_organization));
    }
    
    /**
     * Build and add "other courses" tab.
     */
    private void setupOtherCoursesTab() {
        mTabHost.addTab(mTabHost.newTabSpec(TAG_OTHER_COURSES)
                .setIndicator(buildIndicator(R.string.tab_instructor_other_courses))
                .setContent(R.id.tab_other_course));
    }
    
    /**
     * Build a {@link android.view.View} to be used as a tab indicator, setting the requested string resource as
     * its label.
     * @param textRes
     * @param activity
     * @param rootView
     * @return View
     */
    private View buildIndicator(int textRes) {
        final TextView indicator = (TextView) mActivity.getLayoutInflater()
                .inflate(R.layout.tab_indicator, (ViewGroup) mRootView.findViewById(android.R.id.tabs), false);
        indicator.setText(textRes);
        return indicator;
    }
    
    /**
     * In order to protect the activity from the back stack after a student logs out, remove the activity 
     * If the student hits the back button, this will take them to the Home activity
     */
    private void handleLogout() {
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(Constants.ACTION_LOGOUT);
        mReceiver = new BroadcastReceiver() {
			@Override
			public void onReceive(Context context, Intent intent) {
			    Log.d("onReceive","Logout in progress");
		        intent = new Intent(Intent.ACTION_VIEW, null, mActivity, HomeActivity.class);
		        intent.putExtra(Constants.EXTRA_LOGIN_STATUS, Integer.toString(Constants.LOGIN_STATUS_LOGOUT));
		        
		        mActivity.startActivity(intent); 
			    mActivity.finish();
			}
		};
		
        mActivity.registerReceiver(mReceiver, intentFilter);
    }
    
    /**
     * Determine if the person has logged in and whether there is a person object in the database
     * Get the student's BSU ID for use throughout the application
     */
    private void handleLogin() {
    	Person person = LoginHelper.checkLogin(mActivity);
    	
    	if (person != null) {
    		mBSUID = person.getBSUID();
        	mLoginGuid = person.getLoginGuid();
        	
        	mLogin = true;
    	} else {
	        Intent intent = new Intent(Intent.ACTION_VIEW, null, mActivity, HomeActivity.class);
	        intent.putExtra(Constants.EXTRA_LOGIN_STATUS, Integer.toString(Constants.LOGIN_STATUS_NOT_LOGGED_IN));
	        
	        mActivity.startActivity(intent); 
		    mActivity.finish();
		    
		    mLogin = false;
    	}    	
    }
}
